package com.edu.app.controller.core;

import com.alibaba.fastjson.JSON;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.edu.app.bean.core.*;
import com.edu.app.bean.linkbeans.SysCustomerActivity;
import com.edu.app.bean.linkbeans.SysCustomerLesson;
import com.edu.app.bean.linkbeans.SysUserActivity;
import com.edu.app.bean.virtualbean.SelectedItems;
import com.edu.app.constant.ErrorConstant;
import com.edu.app.constant.StaticConstant;
import com.edu.app.constant.SysMessage;
import com.edu.app.model.ActivityModel;
import com.edu.app.service.sys.app.teacher.SysCutomerActFeedbackService;
import com.edu.app.service.sys.core.SysActivityService;
import com.edu.app.service.sys.core.SysLessonService;
import com.edu.app.service.sys.core.SysListOfValueService;
import com.edu.app.service.sys.core.SysUserService;
import com.edu.app.service.sys.linkservices.SysCustomerActivityService;
import com.edu.app.service.sys.linkservices.SysCustomerLessonService;
import com.edu.app.service.sys.linkservices.SysCustomerTraceService;
import com.edu.app.service.sys.linkservices.SysUserActivityService;
import com.edu.app.service.sys.security.SysSecurityService;
import com.edu.app.util.CommonUtils;
import com.edu.app.util.ErrorUtil;
import com.edu.app.util.JWTUtil;
import com.edu.app.util.MsgUtil;
import com.edu.app.util.alisms.AliyunMessageUtil;

import com.github.pagehelper.PageInfo;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@RequestMapping(value = "/api/activities")
@RestController
public class SysActivityController {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysActivityService sysActivityService;

    @Autowired
    private SysUserActivityService sysUserActivityService;

    @Autowired
    private SysCustomerActivityService sysCustomerActivityService;

    @Autowired
    private SysSecurityService sysSecurityService;

    @Autowired
    private SysCustomerLessonService sysCustomerLessonService;

    @Autowired
    private SysCutomerActFeedbackService sysCutomerActFeedbackService;

    @Autowired
    private SysLessonService sysLessonService;

    @Autowired
    private SysListOfValueService sysListOfValueService;

    @Autowired
    private SysCustomerTraceService sysCustomerTraceService;

    @RequestMapping(value = "")
    @RequiresAuthentication
    public ModelMap getPermissionList (){

        try{
            List<SysActivity> permissionList = sysActivityService.getObjectList();
            return MsgUtil.retMsg(SysMessage.GET_ACTIVITY_SUCCEED, StaticConstant.ACTIVITY_LIST, permissionList);
        }catch(Exception e){
            return ErrorUtil.retErrMsg(e);
        }

    }

    @GetMapping(value = "/{id}")
    @RequiresAuthentication
    public ModelMap getActivityById(@PathVariable Integer id){

        try{
            SysActivity sysActivity  = sysActivityService.getObjectById(id);
            return MsgUtil.retMsg(SysMessage.GET_ACTIVITY_SUCCEED, StaticConstant.ACTIVITY, sysActivity);
        }catch(Exception e){
            return ErrorUtil.retErrMsg(e);
        }

    }

    @GetMapping("/pages")
    @RequiresAuthentication
    public ModelMap getActivityByPage(@RequestParam Integer offset, @RequestParam Integer limit) {

        try {
            PageInfo pageInfo = sysActivityService.findItemByPage(offset, limit);
            return MsgUtil.retMsg(SysMessage.GET_USER_BY_PAGE_SUCCEED, "page_info", pageInfo);
        } catch (Exception e) {
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    @PostMapping(value = "")
    @RequiresAuthentication
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public ModelMap addActivity(@RequestHeader("Authorization") String token,
                                @RequestBody SysActivity sysActivity,
                                @RequestParam String employeeList,
                                @RequestParam String customerList,
                                @RequestParam String rolePlay){

        try{
            String username = JWTUtil.getUsername(token);
            sysActivity.initializeSystemColumns(username);
            Integer r = sysActivityService.add(sysActivity);

            if(r > 0){
                //Assign activity to corresponding users
                List<SelectedItems> selectedItems = JSON.parseArray(employeeList, SelectedItems.class);
                for(int i=0; i<selectedItems.size(); i++){
                    SysUserActivity tmp = new SysUserActivity(selectedItems.get(i).getValue(), sysActivity.getId());
                    tmp.initializeSystemColumns(username);
                    tmp.setRoleplay(rolePlay);
                    sysUserActivityService.add(tmp);
                }

                selectedItems = JSON.parseArray(customerList, SelectedItems.class);
                for(int i=0; i<selectedItems.size(); i++){
                    SysCustomerActivity tmp = new SysCustomerActivity(selectedItems.get(i).getValue(), sysActivity.getId());
                    tmp.initializeSystemColumns(username);
                    sysCustomerActivityService.add(tmp);
                }
            }else{
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
            }
            return MsgUtil.retMsg(SysMessage.ADD_ACTIVITY_SUCCEED, null, null);
        }catch (org.springframework.dao.DuplicateKeyException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(ErrorConstant.ACTIVITY_ALREADY_EXISTS);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }

    }

    @PostMapping(value = "/attachCallActivity")
    @RequiresAuthentication
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public ModelMap attachCallActivity(@RequestHeader("Authorization") String token,
                                       @RequestBody SysActivity sysActivity,
                                       @RequestParam Integer employee_id,
                                       @RequestParam Integer customer_id,
                                       @RequestParam String rolePlay){
        try{
            String username = JWTUtil.getUsername(token);
            sysActivity.initializeSystemColumns(username);
            List<SysListOfValue> sysListOfValueList = sysListOfValueService.getObjectListByType("S_LOV_SALES_PHONE");
            for(SysListOfValue tmp: sysListOfValueList){
                sysActivity.setType_id(tmp.getId());
                break;
            }
            Integer r = sysActivityService.add(sysActivity);

            SysUserActivity tmpUserAct = new SysUserActivity(employee_id, sysActivity.getId());
            tmpUserAct.initializeSystemColumns(username);
            tmpUserAct.setRoleplay(rolePlay);
            sysUserActivityService.add(tmpUserAct);

            SysCustomerActivity tmpCusAct = new SysCustomerActivity(customer_id, sysActivity.getId());
            tmpCusAct.initializeSystemColumns(username);
            sysCustomerActivityService.add(tmpCusAct);

            return MsgUtil.retMsg(SysMessage.ADD_ACTIVITY_SUCCEED, null, null);
        }catch (org.springframework.dao.DuplicateKeyException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(ErrorConstant.ACTIVITY_ALREADY_EXISTS);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }
    }

    @PostMapping(value = "/addActivityWithLoop")
    @RequiresAuthentication
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public ModelMap addActivityWithLoop(@RequestHeader("Authorization") String token,
                                        @RequestBody SysActivity sysActivity,
                                        @RequestParam String employeeList,
                                        @RequestParam String customerList,
                                        @RequestParam Integer loop_value,
                                        @RequestParam String rolePlay){

        try{
            int m=0;
            while(loop_value - m> 0){
                String username = JWTUtil.getUsername(token);
                sysActivity.initializeSystemColumns(username);

                sysActivity.setId(null); //clear up the activity id for next loop insert into database if there is
                Integer r = sysActivityService.add(sysActivity);

                sysActivity.setTime(CommonUtils.getNextWeekDate(sysActivity.getTime(), 7));

                if(r > 0){
                    //Assign activity to corresponding users
                    List<SelectedItems> selectedItems = JSON.parseArray(employeeList, SelectedItems.class);
                    for(int i=0; i<selectedItems.size(); i++){
                        SysUserActivity tmp = new SysUserActivity(selectedItems.get(i).getValue(), sysActivity.getId());
                        tmp.initializeSystemColumns(username);
                        tmp.setRoleplay(rolePlay);
                        sysUserActivityService.add(tmp);
                    }

                    selectedItems = JSON.parseArray(customerList, SelectedItems.class);
                    for(int i=0; i<selectedItems.size(); i++){
                        SysCustomerActivity tmp = new SysCustomerActivity(selectedItems.get(i).getValue(), sysActivity.getId());
                        tmp.initializeSystemColumns(username);
                        sysCustomerActivityService.add(tmp);
                    }
                    m++;
                }else{
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
                }
            }
            return MsgUtil.retMsg(SysMessage.ADD_ACTIVITY_SUCCEED, null, null);
        }catch (org.springframework.dao.DuplicateKeyException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(ErrorConstant.ACTIVITY_ALREADY_EXISTS);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }

    }

    @PutMapping(value = "")
    @RequiresAuthentication
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public ModelMap updateActivity(@RequestHeader("Authorization") String token,
                                   @RequestBody SysActivity sysActivity,
                                   @RequestParam String employeeList,
                                   @RequestParam String customerList,
                                   @RequestParam String rolePlay){

        try{
            String username = JWTUtil.getUsername(token);
            SysActivity dbActivity = sysActivityService.getObjectById(sysActivity.getId());
            BeanUtils.copyProperties(sysActivity, dbActivity, CommonUtils.getNullPropertyNames(sysActivity));
            sysActivity.initializeUpdateSystemColumns(username);

            Integer r = sysActivityService.update(sysActivity);

            //clear up the old relationships
            sysUserActivityService.deleteUserActivityByActivityId(sysActivity.getId());
            sysCustomerActivityService.deleteCustomerActivityByActivityId(sysActivity.getId());

            //Assign activity to corresponding users
            List<SelectedItems> selectedItems = JSON.parseArray(employeeList, SelectedItems.class);
            for(int i=0; i<selectedItems.size(); i++){
                SysUserActivity tmp = new SysUserActivity(selectedItems.get(i).getValue(), sysActivity.getId());
                tmp.initializeSystemColumns(username);
                tmp.setRoleplay(rolePlay);
                sysUserActivityService.add(tmp);
            }

            selectedItems = JSON.parseArray(customerList, SelectedItems.class);
            for(int i=0; i<selectedItems.size(); i++){
                SysCustomerActivity tmp = new SysCustomerActivity(selectedItems.get(i).getValue(), sysActivity.getId());
                tmp.initializeSystemColumns(username);
                sysCustomerActivityService.add(tmp);
            }
            return MsgUtil.retMsg(SysMessage.UPDATE_ACTIVITY_SUCCEED, null, null);
        }catch (org.springframework.dao.DuplicateKeyException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(ErrorConstant.ACTIVITY_ALREADY_EXISTS);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }

    }

    @PatchMapping(value = "/{id}")
    @RequiresAuthentication
    public ModelMap patchActivity (@PathVariable Integer id, @RequestBody SysActivity activity){

        SysActivity sysActivity = sysActivityService.getObjectById(id);

        BeanUtils.copyProperties(activity, sysActivity, CommonUtils.getNullPropertyNames(activity));
        Integer i = sysActivityService.update(sysActivity);
        if(i > 0 ){
            return MsgUtil.retMsg(SysMessage.PATCH_ACTIVITY_SUCCEED, null, null);
        }
        else{
            return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
        }
    }

    @PostMapping(value = "/renewActivity")
    @RequiresAuthentication
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public ModelMap renewActivity(@RequestHeader("Authorization") String token,
                                @RequestBody SysActivity sysActivity,
                                @RequestParam String employeeList,
                                @RequestParam String customerList,
                                @RequestParam String rolePlay,
                                @RequestParam Integer oldActId){

        try{
            //finish the current activity
            SysActivity oldAct = sysActivityService.getObjectById(oldActId);
            oldAct.setStatus(2);
            sysActivityService.update(oldAct);

            String username = JWTUtil.getUsername(token);
            sysActivity.initializeSystemColumns(username);
            Integer r = sysActivityService.add(sysActivity);

            if(r > 0){
                //Assign activity to corresponding users
                List<SelectedItems> selectedItems = JSON.parseArray(employeeList, SelectedItems.class);
                for(int i=0; i<selectedItems.size(); i++){
                    SysUserActivity tmp = new SysUserActivity(selectedItems.get(i).getValue(), sysActivity.getId());
                    tmp.initializeSystemColumns(username);
                    tmp.setRoleplay(rolePlay);
                    sysUserActivityService.add(tmp);
                }

                selectedItems = JSON.parseArray(customerList, SelectedItems.class);
                for(int i=0; i<selectedItems.size(); i++){
                    SysCustomerActivity tmp = new SysCustomerActivity(selectedItems.get(i).getValue(), sysActivity.getId());
                    tmp.initializeSystemColumns(username);
                    sysCustomerActivityService.add(tmp);
                }
            }else{
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ErrorUtil.retErrMsg(ErrorConstant.SERVER_INTERNAL_ERROR);
            }
            return MsgUtil.retMsg(SysMessage.ADD_ACTIVITY_SUCCEED, null, null);
        }catch (org.springframework.dao.DuplicateKeyException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(ErrorConstant.ACTIVITY_ALREADY_EXISTS);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }

    }

    @PostMapping(value="/completeActivity")
    @RequiresAuthentication
    public ModelMap completeActivity(@RequestParam Integer id, @RequestParam Integer status){
        try{
            SysActivity sysActivity = sysActivityService.getObjectById(id);
            //complete the activity
            sysActivity.setStatus(status);
            sysActivityService.update(sysActivity);
            return MsgUtil.retMsg(SysMessage.COMPLETE_ACTIVITY_SUCCEED, null, null);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }

    @PostMapping(value = "/completeLesson")
    @RequiresAuthentication
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public ModelMap completeLesson (@RequestHeader("Authorization") String token,
                                    @RequestParam Integer id,
                                    @RequestParam Integer lesson_id,
                                    @RequestParam String lessonType,
                                    @RequestParam String time,
                                    @RequestParam String teacher){

        try{
            String username = JWTUtil.getUsername(token);
            SysActivity sysActivity = sysActivityService.getObjectById(id);

            //Check if the current users are legal to complete the lesson
            for(SysCustomer sysCustomer: sysCustomerActivityService.getCustomerByActivityId(id)){
                SysCustomerLesson sysCustomerLesson = sysCustomerLessonService.getCustomerLesson(sysCustomer.getId(), lesson_id);
                if(sysCustomerLesson == null){
                    return ErrorUtil.retErrMsg(ErrorConstant.USER_LESSON_NOT_EXISTS);
                }
            }

            //Once we come here, means everything is legal, set status as 1, means this activity wait for feedback
            sysActivity.setStatus(StaticConstant.ACT_PENDING_CONFIRM);
            sysActivityService.update(sysActivity);

            for(SysCustomer sysCustomer: sysCustomerActivityService.getCustomerByActivityId(id)){

                SysCustomerLesson sysCustomerLesson = sysCustomerLessonService.getCustomerLesson(sysCustomer.getId(), lesson_id);
                sysCustomerLesson.setPoints(sysCustomerLesson.getPoints()-1);
                sysCustomerLessonService.update(sysCustomerLesson);

                sendSMS(sysCustomer.getName(),teacher,sysCustomerLesson.getPoints(),sysCustomer.getPhone(),lessonType,time);

                //Adding corresponding trace details
                SysListOfValue sysListOfValueTmp = sysListOfValueService.getObjectById(sysActivity.getType_id());
                SysUser sysUserTmp = sysUserService.getUserByName(username);
                String content = "刷1节" + sysListOfValueTmp.getValue() + "课。老师：" + sysUserTmp.getNickname() + "，时间：" + CommonUtils.dateToString(sysActivity.getTime());
                SysCustomerTrace sysCustomerTrace = new SysCustomerTrace();
                sysCustomerTrace.initializeSystemColumns(username);
                sysCustomerTrace.setContent(content);
                sysCustomerTrace.setCustomer_id(sysCustomer.getId());
                sysCustomerTraceService.add(sysCustomerTrace);
            }

            Integer pendingNum = sysUserActivityService.getUserPendingActivityNumber(username, "S_LOV_LESSON", "teacher");
            ModelMap map = MsgUtil.retMsg(SysMessage.COMPLETE_ACTIVITY_SUCCEED, null, null);
            map.addAttribute("pendingActNum", pendingNum);
            return map;
        }catch(Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }
    }

    private void sendSMS(String name, String teacher, Integer points, String phone, String lessonType, String time){
        Map<String, String> param = sysSecurityService.getSMSParam(name, teacher, points, phone.replace(" ",""),lessonType,time);
        try{
            AliyunMessageUtil.sendSms(param);
        }catch(Exception e){
        }
    }

    @DeleteMapping(value = "")
    @RequiresAuthentication
    @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT,timeout=36000,rollbackFor=Exception.class)
    public ModelMap delete (@RequestParam Integer id){
        try{
            //Make sure the following deletings are atomic

            //to delete all feedback related wiith current activity
            List<SysCustomer> sysCustomerList = sysCustomerActivityService.getCustomerByActivityId(id);
            for(SysCustomer sysCustomer: sysCustomerList){
                SysCustomerActivity sysCustomerActivity = sysCustomerActivityService.getCustomerActivity(sysCustomer.getId(), id);
                sysCutomerActFeedbackService.deleteCustomerActFeedbackByActId(sysCustomerActivity.getId());
            }

            sysCustomerActivityService.deleteCustomerActivityByActivityId(id);
            sysUserActivityService.deleteUserActivityByActivityId(id);
            sysActivityService.delete(id);
            return MsgUtil.retMsg(SysMessage.DELETE_ACTIVITY_SUCCEED, null, null);
        }catch(Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ErrorUtil.retErrMsg(e);
        }
    }

    @GetMapping(value = "/getActivityModel")
    public ModelMap getActivityModel(@RequestParam Integer id){

        try{
            ActivityModel activityModel = sysActivityService.getActivityModelById(id);
            return MsgUtil.retMsg(SysMessage.GET_ACTIVITY_MODEL_SUCCEED, "activity_model", activityModel);
        }catch (Exception e){
            return ErrorUtil.retErrMsg(e);
        }
    }
}
